#!/bin/bash

# 当前时间
current_date=$(date +"%Y%m%d")

# Function to show help message
# 显示帮助信息的功能
function show_help() {
    echo "Usage: seek [-k|--keywords keywords] [-d|--search-dirs search_dirs] [-s|--system-info system_infos] [-h|--help]"
    echo ""

    echo "Options (选项):"
    echo "  -k, --keywords TERM1,TERM2    Specify search keywords directly (指定关键词)"
    echo "  -i, --input-file FILE         Specify search keyword file (指定关键词文件)"
    echo "  -f, --file-type TYPE          Specify custom file type for search (指定自定义的文件类型进行搜索) (default: fq.gz and fastq.gz)"
    echo "  -o, --output-file FILE        Specify output file (指定结果文件) (default: seek_results_{timestamp}.txt)"
    echo "  -s, --system-info FILE        Specify system information file (指定服务器信息) (default: seek_servers.txt)"
    echo "  -d, --search-dirs DIR/FILE    Specify search directories from a file or directly (指定搜索目录数组或文件)"
    echo "  -t, --transfer-dir DIR        Specify transfer directory (指定传输和传输路径) (default: transfer dir ./data)"
    echo "  -m, --missing-terms FILE      Specify missing terms file (指定未匹配关键词文件) (default: seek_missing_terms_{timestamp}.txt)"
    echo "  -r, --repeat-search OPTION    Specify duplicate search option for IPs and directories (指定重复搜索):"
    echo "                                'all' - Search all IPs and directories (重复IP和目录) (default: False)"
    echo "                                'ip'  - Search duplicate IPs (重复IP) (default: False)"
    echo "                                'dir' - Search duplicate directories (重复目录) (default: False)"
    echo "  --ignore-local                Specify whether to ignore local servers (指定是否忽略本地服务器) (default: False)"
    echo "  -h, --help                    Show this help message (帮助信息)"
    echo ""

    echo "Note (注意):"
    echo "  - Either -k [keyword option] or -i [keyword file], -s (servers file or default file) and "
    echo "           -d [search dir or file] options are mandatory. (搜索必备参数)"
    echo "  - Other options are optional. (可选参数)"
    echo ""

    echo "Input specification (输入规范):"
    echo "When multiple option inputs are required for -k or -d, the following format can be followed (-k or -n 输入格式)"
    echo "- Rule 1"
    echo "  - List, array, dictionary, etc. enclosed in single or double quotation marks separated by commas, spaces, commas+spaces:"
    echo "    (以逗号、空格、逗号+空格分隔，单双引号包裹的列表、数组、字典等)"
    echo "    - '(keyword(dir)', 'keyword(dir)')'"
    echo "    - '('keyword(dir)' 'keyword(dir)')'"
    echo "    - '{'keyword(dir)', 'keyword(dir)'}'"
    echo "    - '{'keyword(dir)' 'keyword(dir)'}'"
    echo "    - '['keyword(dir)', 'keyword(dir)']'"
    echo "    - '['keyword(dir)' 'keyword(dir)']'"
    echo "    - 'keyword(dir) keyword(dir)'"
    echo "    - 'keyword(dir), keyword(dir)'"
    echo "- Rule 2"
    echo "  - A closely connected list, dictionary, tuple, etc. separated by commas:"
    echo "    (以逗号分割，紧密相连的列表、字典、元组等)"
    echo "    - ('keyword(dir)','keyword(dir)')"
    echo "    - {'keyword(dir)','keyword(dir)'}"
    echo "    - ['keyword(dir)','keyword(dir)']"
    echo "    - keyword(dir),keyword(dir)"
    echo ""

    echo "Examples (举例):"
    echo "  seek -k 'keyword1,keyword2' -d '/path/to/dir1/ /path/to/dir2/' -s       指定关键词数组、搜索目录数组、默认服务器信息搜索 (不保存不传输)"
    echo "  seek -i keywords.txt -d search_dirs.txt -s servers.txt                  指定关键词文件、搜索目录文件、服务器信息搜索 (不保存不传输)"
    echo "  seek -i keywords.txt -d search_dirs.txt -s servers.txt -o -t -m         指定必要参数搜索外，提供保存文件、传输文件、失败文件 (保存并传输)"
    echo "  seek -i keywords.txt -d search_dirs.txt -s servers.txt -r               指定必要参数搜索外，指定-r可进行IP和目录重复搜索 (传输覆盖保存最后一次)"
    echo "  seek -i keywords.txt -d search_dirs.txt -s servers.txt -f somatic.xlsx  指定自定义的文件类型进行搜索 (如搜索*.somatic.xlsx文件)"
    echo ""

    echo "Quick commands (快捷指令):"
    echo "  - Enter multiple keywords (多关键词写文件):"
    echo "    - echo 'NGS230723-723 NGS230723-724' | tr ' ' '\n' > sampleID.txt"
    echo "    - array=('NGS230723-723WX', 'NGS230723-724WE'); for item in '\${array[@]}'; do echo '\${item%,}'; done > sampleSn.txt"
    echo ""

    echo "  - Enter multiple directories (多搜索目录写文件):"
    echo "    - echo '/data/files/raw/ /data/files/clean' | tr ' ' '\n' > paths.txt"
    echo ""

    echo "  - Enter multiple serverInfos (多服务器信息写文件)"
    echo "    - printf '%s\n' '127.0.0.1 username password' '127.0.0.2 username password' > servers.txt"
    echo "    - echo '127.0.0.3 username password' >> servers.txt"
    echo ""

}


# Function to remove outer quotes from a string
# 用于从字符串中移除外引号的函数
function remove_outer_chars() {
    local str="$1"
    str="${str#"${str%%[![:space:]]*}"}"    # Trim leading whitespace | 去除字符串开头的空格
    str="${str%"${str##*[![:space:]]}"}"    # Trim trailing whitespace | 去除字符串末尾的空格
    str="${str%\"}"                         # Remove leading double quote | 去除字符串开头的双引号
    str="${str#\"}"                         # Remove trailing double quote | 去除字符串末尾的双引号
    str="${str%\'}"                         # Remove leading single quote | 去除字符串开头的单引号
    str="${str#\'}"                         # Remove trailing single quote | 去除字符串末尾的单引号
    str="${str%\]}"                         # Remove leading closing bracket | 去除字符串开头的闭合方括号
    str="${str#\[}"                         # Remove trailing opening bracket | 去除字符串末尾的开启方括号
    str="${str%\}}"                         # Remove leading closing brace | 去除字符串开头的闭合大括号
    str="${str#\{}"                         # Remove trailing opening brace | 去除字符串末尾的开启大括号
    echo "$str"
}


# Obtain the local IP address
# 获取本机IP地址
function get_local_ip() {
    if [ -f "/etc/centos-release" ]; then
        ip_address=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
    elif [ -f "/etc/lsb-release" ]; then
        ip_address=$(ip -4 addr show em1 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
    else
        echo "WARNING: Unsupported operating system."
        ip_address="127.0.0.1"
    fi
    echo $ip_address
}


# Convert byte count to human readable size format
# 将字节数转换为人类可读的大小格式
function human_readable_size {
    local size_in_bytes="$1"

    if [ "$size_in_bytes" -lt 1024 ]; then
        echo "${size_in_bytes} bytes"
    elif [ "$size_in_bytes" -lt 1048576 ]; then
        echo "$(bc <<< "scale=2; $size_in_bytes / 1024") KB"
    elif [ "$size_in_bytes" -lt 1073741824 ]; then
        echo "$(bc <<< "scale=2; $size_in_bytes / 1048576") MB"
    else
        echo "$(bc <<< "scale=2; $size_in_bytes / 1073741824") GB"
    fi
}

# Used to check if the directory exists, create if it does not exist
# 函数用于检查目录是否存在，不存在则创建
function ensure_directory() {
    local dir="$1"
    if [[ ! -d "$dir" ]]; then
        mkdir -p "$dir"
        echo "WARNING: The directory did not exist and has been created (该目录不存在，已创建): $dir"
    fi
}

# Fix CR LF issues
# 修复 CR LF 问题
function fix_crlf() {
    local file="$1"

    # Check if the file exists
    if [[ ! -f "$file" ]]; then
        echo "Error: File does not exist."
        return 1
    fi

    # Check if the file is writable
    if [[ ! -w "$file" ]]; then
        echo "Error: File is not writable."
        return 1
    fi

    # Check if the directory is writable (for creating the temporary file)
    local dir
    dir=$(dirname "$file")
    if [[ ! -w "$dir" ]]; then
        echo "Error: Directory is not writable."
        return 1
    fi

    # Check for Windows line endings and convert the file
    if grep -q $'\r' "$file"; then
        echo "INFO: Windows line endings detected in $file."

        # Use dos2unix if available
        if command -v dos2unix >/dev/null; then
            echo "INFO: Converting with dos2unix..."
            dos2unix "$file" || { echo "INFO: dos2unix failed to convert the file."; return 1; }
        
        # Otherwise, use tr and create a temporary file in the same directory
        else
            echo "INFO: dos2unix not found. Converting with tr..."
            local tmp_file="${dir}/$(basename "$file").tmp"
            tr -d '\r' < "$file" > "$tmp_file" && mv "$tmp_file" "$file" || {
                echo "INFO: Conversion failed. Could not remove Windows line endings."
                rm -f "$tmp_file"  # Clean up any temporary file created in case of failure
                return 1
            }
        fi
    else
        echo "INFO: No Windows line endings in $file."
    fi
    return 0
}


# Processing files and arrays
# 处理文件和数组
function process_input() {
    local input="$1"
    # Use name reference to pass the result array to the function
    # 使用名称引用，将结果数组传递给函数
    # local -n ref_array=$2 # bash 4.3 版本中引入的特性
    local ref_array=$2

    # Check if input is a file
    # 检查输入是否为文件
    if [[ -f "$input" ]]; then
        # Fix possible Windows carriage returns
        # 修复可能的 Windows 回车符
        fix_crlf "$input"

        while IFS= read -r line || [[ -n "$line" ]]; do
            # Remove leading/trailing whitespace and skip comment lines
            # 去除行首尾的空格并跳过注释行
            clean_line=$(echo "$line" | grep -vE '^\s*#|^\s*$' | xargs)
            if [[ -n "$clean_line" ]]; then
                # ref_array+=("$clean_line") # 与local -n一起使用

                # Dynamically appending to an array using eval
                # 使用 eval 动态追加到数组
                eval "$ref_array+=(\"\$clean_line\")" 
            fi
        done < "$input"

    else
        # Remove outer characters using your function
        # 删除外括号、单引号、双引号、大括号和大括号
        local input_string=$(remove_outer_chars "$input")
        # Splitting strings into arrays
        # 分割字符串到数组
        IFS=', ' read -r -a temp_array <<< "$input_string"
        # Remove leading/trailing parentheses and spaces from each search term
        # 从每个搜索词中删除前导/尾随括号和空格
        for i in "${!temp_array[@]}"; do
            temp_array[$i]="${temp_array[$i]#(}"
            temp_array[$i]="${temp_array[$i]%)}"
            temp_array[$i]=$(echo "${temp_array[$i]}" | xargs)
        done
        # Setting an array using eval
        # 使用 eval 设置数组
        eval "$ref_array=(\"\${temp_array[@]}\")"
    fi
}


# 函数用来从一个相对路径获取绝对路径
# Function to get an absolute path from a relative path
function get_absolute_path() {
    local input_path="$1"  # 用户提供的输入路径
    local absolute_path

    # 检查输入的路径是否已经是绝对路径
    # Check if the input is already an absolute path
    if [[ "$input_path" == /* ]]; then
        absolute_path="$input_path"
    # 检查是否安装有 realpath 命令
    # Check if realpath is available
    elif command -v realpath &> /dev/null; then
        absolute_path=$(realpath "$input_path")
    # 如果没有 realpath，检查 readlink 命令是否可用
    # If realpath is unavailable, check if readlink is available
    elif command -v readlink &> /dev/null; then
        absolute_path=$(readlink -f "$input_path")
    else
        # 作为后备，检查路径是否为相对路径，尝试在前面添加当前目录
        # As a fallback, check if the path is relative and attempt to prepend the current directory
        if [[ "$input_path" == .* || "$input_path" == */* ]]; then
            absolute_path="$(pwd)/$input_path"
            echo "WARNING: 'realpath' and 'readlink' commands are not available. Using best guess for absolute path. (警告：'realpath' 和 'readlink' 命令不可用。使用最佳猜测来获取绝对路径。)" >&2
        else
            absolute_path="$input_path"
            echo "WARNING: 'realpath' and 'readlink' commands are not available. Assuming path is absolute. (警告：'realpath' 和 'readlink' 命令不可用。假设路径已经是绝对路径。)" >&2
        fi
    fi

    # 输出绝对路径
    # Output the absolute path
    echo "$absolute_path"
    return 0
}


# Initialize variables
# 初始化变量
use_keywords=false
use_input_file=false
use_servers=false
use_dirs=false
use_file_type=false
use_output_file=false
use_transfer=false
use_search_ips=false
use_search_dirs=false
use_missing_file=false
use_ignore_local=false

# Check if no options are provided
# 检查是否未提供任何选项
if [[ $# -eq 0 ]]; then
    echo "Usage: seek -h/--help for help"
    exit 1
fi

# Parse command-line options
# 分析命令行选项
while [[ $# -gt 0 ]]; do
    case $1 in
        -k|--keywords)
            if [[ -n "$2" ]]; then
                process_input "$2" search_terms
                use_keywords=true
                shift 2
            else
                echo "ERROR: Missing search keywords argument for -k option. (缺少-k选项的搜索关键字参数。)"
                echo "Please use -h or --help option to view help for correct usage."
                exit 1
            fi
        ;;
        -i|--input-file)
            if [[ -n "$2" ]]; then
                process_input "$2" search_terms
                use_input_file=true
                shift 2
            else
                echo "ERROR: Missing file argument for -i option. (-i选项缺少文件参数。)"
                echo "Please use -h or --help option to view help for correct usage."
                exit 1
            fi
        ;;
        -f|--file-type)
            if [[ -n "$2" ]]; then
                use_file_type=true
                file_type="$2"
                shift 2
            else
                echo "ERROR: Missing file type argument for -f option. (-f选项缺少文件类型参数。)"
                echo "Please use -h or --help option to view help for correct usage."
                exit 1
            fi
        ;;
        -o|--output-file)
            use_output_file=true
            if [[ -n "$2" && ! "$2" == -* ]]; then
                output_file=$(get_absolute_path "$2")
                echo "INFO: Using provided output file (使用提供的输出文件): $output_file"
                shift 2
            else
                output_file=$(get_absolute_path "seek_results_${current_date}.txt")
                echo "INFO: Using default output file (使用默认输出文件): $output_file"
                shift 1
            fi
        ;;
        -s|--servers-info)
            use_servers=true
            if [[ -n "$2" && ! "$2" == -* ]]; then
                servers_info="$2"
                echo "INFO: Using provided servers info file (使用提供的服务器信息文件): $servers_info"
                shift 2
            else
                servers_info="$(dirname "$(dirname "$0")")/extdata/seek_servers.txt"
                echo "INFO: Using default servers info file (使用默认的服务器信息文件): $servers_info"
                shift 1
            fi
        ;;
        -d|--search-dirs)
            use_dirs=true
            if [[ -n "$2" && ! "$2" == -* ]]; then
                process_input "$2" search_dirs
                echo "INFO: Using provided search directory list (使用提供的搜索目录列表): ${search_dirs[@]}"
                shift 2
            else
                echo "ERROR: Missing search directories argument for -d option. (-d选项缺少目录参数。)"
                echo "Please use -h or --help option to view help for correct usage."
                exit 1
        fi
        ;;
        -t|--transfer-dir)
            use_transfer=true
            if [[ -n "$2" && ! "$2" == -* ]]; then
                saved_dir=$(get_absolute_path "$2")
                echo "INFO: Using provided transfer directory (使用提供的传输目录): $saved_dir"
                shift 2
            else
                saved_dir="$(pwd)/data"
                echo "INFO: Using default transfer directory (使用默认传输目录): $saved_dir"
                shift 1
            fi
            ensure_directory "$saved_dir"
        ;;
        -m|--missing-terms)
            use_missing_file=true
            if [[ -n "$2" && ! "$2" == -* ]]; then
                missing_terms_file=$(get_absolute_path "$2")
                echo "INFO: Using provided missing terms file (使用提供的缺失术语文件): $missing_terms_file"
                shift 2
            else
                missing_terms_file=$(get_absolute_path "seek_missing_terms_${current_date}.txt")
                echo "INFO: Using default missing terms file (使用默认缺少的术语文件): $missing_terms_file"
                shift 1
            fi
        ;;
        -r|--repeat-search)
            case "$2" in
                all)
                    use_search_ips=true
                    use_search_dirs=true
                    echo "INFO: Using provided duplicate repeat search option for all IPs and directories (使用提供的重复搜索选项): all IPs and directories"
                    shift 2
                ;;
                ip)
                    use_search_ips=true
                    echo "INFO: Using provided duplicate repeat search option for all IPs (使用提供的重复搜索选项): all IPs"
                    shift 2
                ;;
                dir)
                    use_search_dirs=true
                    echo "INFO: Using provided duplicate repeat search option for all directories (使用提供的重复搜索选项): all directories"
                    shift 2
                ;;
                *)
                    echo "ERROR: Unknown value for -r|--repeat-search (未知值): $2"
                    echo "Please use -h or --help option to view help for correct usage."
                    exit 1
                ;;
            esac
        ;;
        --ignore-local)
            use_ignore_local=true
            shift 1
        ;;
        -h|--help)
            show_help
            exit 0
        ;;
        *)
            echo "ERROR: Unrecognized option (无法识别的选项): $1"
            echo "Please use -h or --help option to view help for correct usage."
            exit 1
        ;;
    esac
done

# Check for mutually exclusive options
# 检查互斥选项
if "$use_keywords" && "$use_input_file"; then
  echo "ERROR: -k and -i options are mutually exclusive. Please use only one of them.(-k 和 -i 选项互斥。请只使用其中一个。)"
  echo "Please use -h or --help option to view help for correct usage."
  exit 1
fi

# Check if necessary parameters are missing
# 检查是否缺少必要参数
if { ! "$use_keywords" && ! "$use_input_file"; } || ! "$use_dirs" || ! "$use_servers"; then
    echo "ERROR: Missing necessary options(缺少必要参数)."
    echo "seek -i/--input-file [keyword file] or -k/--keywords [keyword option], -s|--servers-info, -d/--search-dirs [search dir or file]."
    echo "Please use -h or --help option to view help for correct usage."
    exit 1
fi

# Start cross server disk scanning
# 启动跨服务器磁盘扫描
echo ""
echo "----------------------- Start Cross Server Disk Scan (启动跨服务器磁盘扫描) -----------------------"

# Output IP and file headers to the result file
# 输出IP和file的标题到结果文件中
if "$use_output_file"; then
    echo -e "server_ip\tmatch_file\tterm" > "$output_file"
fi

for term in "${search_terms[@]}"; do
    echo ""
    echo "LOGGING: -- $(date --rfc-3339=seconds) -- Scanning in search terms (正在扫描搜索词) -- ${term}"

    # Is the keyword found with a tag
    # 关键词是否找到标记
    term_found=false

    # Split keyword syntax
    # 拆分关键词语法
    prefix="${term%-*}"
    suffix="${term##*-}"

    while read -r ip username password; do
        if [ -z "$ip" ] || [ -z "$username" ] || [ -z "$password" ]; then
            echo "ERROR: -- $(date --rfc-3339=seconds) -- Invalid input in servers_info file (servers_info文件输入无效)" >&2
            continue
        fi

        # Initialize to a state without using control paths
        # 初始化为不使用控制路径的状态
        use_control_path=false
        control_path=""

        echo "LOGGING: -- $(date --rfc-3339=seconds) -- Scanning remote server (正在扫描远程服务器) -- $ip"

        # Skip local server
        # 跳过本地服务器
        local_ip=$(get_local_ip)
        if [ "$ip" == "$local_ip" ] && "$use_ignore_local"; then
            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Skipping local server (跳过本地服务器) -- $ip"
            continue
        fi

        # Check if the current server can be accessed
        # 检查是否可以访问当前服务器
        if ! ping -c 1 -W 1 "$ip" >/dev/null; then
            echo "WARNING: -- $(date --rfc-3339=seconds) -- Server $ip is not reachable. (无法访问服务器)" >&2
            continue
        fi

        # Check if the local system can use ControlMaster, that is, attempt to create a temporary file on the local system
        # 检查本地系统是否可以使用 ControlMaster，即尝试在本地系统上创建一个临时文件
        local_write_test=$(mktemp /tmp/ssh_control.XXXXXX 2>/dev/null)

        if [ -n "$local_write_test" ]; then
            # User has write permission, set control path
            # 用户有写权限，设置控制路径
            use_control_path=true
            control_path=$local_write_test
            trap "rm -f $control_path" EXIT
            ssh_options="-o ControlMaster=auto -o ControlPath=$control_path -o ControlPersist=60s"
            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Using ControlMaster for faster SSH connections (使用ControlMaster加速SSH连接)"
        else
            # User does not have write permission and does not use control path
            # 用户没有写权限，不使用控制路径
            ssh_options=""
            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Standard SSH connection (使用标准SSH连接)"
        fi

        # Test SSH connection by running a simple command
        # 通过运行一个简单的命令测试SSH连接
        sshpass -p "$password" ssh -qn $ssh_options -o ConnectTimeout=60 "${username}@${ip}" "echo 'LOGGING: -- $(date --rfc-3339=seconds) -- SSH connection successful (SSH连接成功)'"

        for ((i=${#search_dirs[@]}-1; i>=0; i--)); do
            dir="${search_dirs[i]}"
            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Searching in search directories (正在扫描搜索目录) -- ${dir}"

            # Based on the above conditions, use the corresponding ssh_options for SSH connection and subsequent operations
            # 根据上面的条件，使用相应的ssh_options进行SSH连接和后续操作

            # Perform remote search and store results in a variable, You can customize the file type or use the default (*.fq.gz and *.fastq.gz)
            # 执行远程搜索并将结果存储在变量中，可自定义换文件类型，或是使用默认的 (*.fq.gz 和 *.fastq.gz)
            if "$use_file_type" && [ -n "$file_type" ]; then
                remote_files=$(sshpass -p "$password" ssh -qn $ssh_options -o ConnectTimeout=60 "${username}@${ip}" "find $dir -type f -maxdepth 4 -name '*${prefix}*-${suffix}*.$file_type' -print 2>/dev/null")
            else
                remote_files=$(sshpass -p "$password" ssh -qn $ssh_options -o ConnectTimeout=60 "${username}@${ip}" "find $dir -type f -maxdepth 4 \( -name '*${prefix}*-${suffix}*.fq.gz' -o -name '*${prefix}*-${suffix}*.fastq.gz' \) -print 2>/dev/null")
            fi

            # Print matching situation
            # 打印匹配情况
            RED='\033[0;36m' # 青色颜色代码
            NC='\033[0m'     # 恢复默认颜色代码
            if [ -n "$remote_files" ]; then
                echo -e "LOGGING: -- $(date --rfc-3339=seconds) -- Match to remote file (匹配到远程文件):\n${RED}$remote_files${NC} "
                term_found=true
            else
                echo -e "LOGGING: -- $(date --rfc-3339=seconds) -- Remote file not matched in $ip (未匹配到远程文件)"
            fi

            if [ -n "$remote_files" ]; then
                # Obtain files with the same name from different paths
                # 获取不同路径的同名文件
                unique_names=($(echo "$remote_files" | awk -F'/' '{print $NF}' | sort -u))

                # 如果同名文件数量与远程文件数量相同，直接进行传输
                if [ ${#unique_names[@]} -eq $(echo "$remote_files" | wc -l) ]; then
                    echo "LOGGING: -- $(date --rfc-3339=seconds) -- No duplicates found in matching remote files (匹配的远程文件无重复)"
                    # Implement transfer matching files based on the input - t parameter
                    # 根据输入的-t参数实现传输匹配文件
                    if "$use_transfer"; then
                        echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transfer directory (传输目录) -- $saved_dir"

                        # Loop through each remote file path
                        # 循环通过每个远程文件路径
                        while IFS= read -r file_path; do
                            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transferring remote files (正在传输远程文件) -- $file_path"

                            sshpass -p "$password" scp -o ConnectTimeout=60 "${username}@${ip}:\"$file_path\"" "$saved_dir"

                            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transfer completed (传输完成)"

                        done <<< "$remote_files"
                    fi

                    # Save matching files based on the input -o parameter
                    # 根据输入的-o参数实现保存匹配文件
                    if "$use_output_file"; then
                        while IFS= read -r file_path; do
                            echo -e "${ip}\t${file_path}\t${term}" >> "$output_file"
                        done <<< "$remote_files"
                        echo "LOGGING: -- $(date --rfc-3339=seconds) -- Matching file successfully written (匹配文件写入成功)"
                    fi

                else
                    echo "LOGGING: -- $(date --rfc-3339=seconds) -- Duplicate matching remote file (匹配的远程文件出现重复)"

                    # Check and transfer files with larger sizes
                    # 检查并传输大小较大的文件
                    for name in "${unique_names[@]}"; do
                        echo "LOGGING: -- $(date --rfc-3339=seconds) -- Comparing remote files for name (正在比较远程文件的名称): $name"
                        matching_files=($(echo "$remote_files" | grep -E "/[^/]*$name$"))

                        largest_size=0
                        largest_file=""

                        echo "LOGGING: -- $(date --rfc-3339=seconds) -- Checking remote file size (正在检查远程文件大小)"
                        for file_path in "${matching_files[@]}"; do
                            file_size=$(sshpass -p "$password" ssh -qn "${username}@${ip}" "stat -c %s \"$file_path\"")

                            human_readable_file_size=$(human_readable_size "$file_size")
                            echo "$file_path (Size: $human_readable_file_size)"

                            if [ "$file_size" -gt "$largest_size" ]; then
                                largest_size="$file_size"
                                largest_file="$file_path"
                            fi
                        done

                        echo -e "LOGGING: -- $(date --rfc-3339=seconds) -- Select the largest remote file(选择最大的远程文件)\n$largest_file"

                        # Implement transfer matching files based on the input -t parameter
                        # 根据输入的-t参数实现传输匹配文件
                        if [ -n "$largest_file" ] && "$use_transfer"; then
                            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transfer directory (传输目录) -- $saved_dir"
                            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transferring remote files (正在传输远程文件) -- $largest_file"

                            sshpass -p "$password" scp -o ConnectTimeout=60 "${username}@${ip}:\"$largest_file\"" "$saved_dir"

                            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transfer completed (传输完成)"
                        fi

                        # Save matching files based on the input -o parameter
                        # 根据输入的-o参数实现保存匹配文件
                        if [ -n "$largest_file" ] && "$use_output_file"; then
                            echo -e "${ip}\t${largest_file}" >> "$output_file"
                            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Matching file successfully written (匹配文件写入成功)"
                        fi
                    done
                fi
            fi

            # Jump out of loop when a file is found in the provided directory and the type of \
            # -r repeated search is not specified (Default non duplicate directory search))
            # 在提供目录中找到文件且指定未指定-r重复搜索的类型时跳出循环（默认不重复目录搜索）
            if "$term_found" && ! "$use_search_dirs"; then
                echo "LOGGING: -- $(date --rfc-3339=seconds) -- Jump out of search directory loop (跳出搜索目录循环)"
                break
            fi

        done # end of search_dirs loop

        # Jump out of loop when the provided IP finds a file and the type of \
        # -r repeated search is not specified (default does not repeat IP search)
        # 在提供的ip找到文件且且指定未指定-r重复搜索的类型时跳出循环（默认不重复ip搜索）
        if "$term_found" && ! "$use_search_ips"; then
            echo "LOGGING: -- $(date --rfc-3339=seconds) -- Jump out of search IP loop (跳出搜索IP循环)"
            break
        fi

        # Close control path at the end of the loop
        # 循环结束时关闭控制路径
        if $use_control_path ; then
            # 捕获“Exit request sent.”消息，并保存到变量中
            exit_message=$(ssh -O exit -o ControlPath="$control_path" "${username}@${ip}" 2>&1)
            
            # 检查操作是否成功，并以自定义格式打印消息
            if [ $? -eq 0 ]; then
                echo "LOGGING: -- $(date --rfc-3339=seconds) -- ControlMaster connection closed. Message: $exit_message"
            else
                echo "ERROR: -- $(date --rfc-3339=seconds) -- Failed to close ControlMaster connection. Message: $exit_message" >&2
            fi
        fi

    done < "$servers_info" # end of servers loop

    # Unmatched keywords written to file
    # 未匹配关键词写入文件
    if "$use_missing_file" && ! "$term_found"; then
        echo "WARNING: -- $(date --rfc-3339=seconds) -- Keyword not found in the provided IP and directory (关键词未在提供的ip和目录中搜索到) -- $term"
        echo "$term" >> "$missing_terms_file"
    fi

done # end of search_terms loop

echo ""
echo "----------------------- Turn off cross server disk scanning (关闭跨服务器磁盘扫描) -----------------------"
echo ""

echo "LOGGING: -- $(date --rfc-3339=seconds) -- Scan completed(扫描完成)"

if "$use_output_file"; then
    echo "LOGGING: -- $(date --rfc-3339=seconds) -- Search results file (搜索结果文件) -- $output_file"
fi

if "$use_transfer"; then
    echo "LOGGING: -- $(date --rfc-3339=seconds) -- Transfer result directory (传输结果目录) -- $saved_dir"
fi

if "$use_missing_file"; then
    echo "LOGGING: -- $(date --rfc-3339=seconds) -- Key files not matched (未匹配关键文件) -- $missing_terms_file"

    # Deduplication of term files not found
    # 对未找到关键词文件进行去重
    sort -u "$missing_terms_file" -o "$missing_terms_file"
fi

echo ""
